<template>
	<div class="group-filter-wrapper" @dragover.prevent.stop="handleDragOver" @dragleave="handleDragLeave"
		@drop.stop="handleDrop" ref="dropZone" draggable="false">

		<transition name="el-zoom-in-center-y">
			<div class="div-first" v-show="!isCollapsed">
				<div v-for="(rule, index) in group.rules" :key="rule.$id || index"
					:class="`group-filter-item ${isConditionGroup(rule) ? 'group-filer-children' : ''}`">
					<group v-if="isConditionGroup(rule)" @update-group="updateChildGroup(index, $event)"
						@delete-group="deleteChildGroup(index)" :group="rule" :depth="depth + 1" :options="options">
					</group>
					<template v-else>
						<itemRule :group="group.rules" :fieldVal="rule" @delete-rule="deleteChildRule(index)"
							@add-rule="addRuleOrGroup('rule', index)" @add-group="addRuleOrGroup('group', index)"
							@add-aggregate="addRuleOrGroup('aggregate', index)"
							@copy-rule="copyRule(index)" :depth="depth" :options="options"></itemRule>
					</template>
				</div>
				<div v-if="!(group.rules && group.rules.length)" class="plus-btn">
					<el-button @click="addRuleOrGroup('rule')" icon="el-icon-plus" plain>添加条件</el-button>
					<el-button @click="addFunction('function')" icon="el-icon-plus" plain>添加执行</el-button>
					<el-button @click="addRuleOrGroup('group')" icon="el-icon-plus" plain>添加条件组</el-button>
					<el-button @click="addRuleOrGroup('aggregate')" icon="el-icon-plus" plain>添加聚合组</el-button>
					<el-button @click="addTrigger('trigger')" icon="el-icon-plus" plain>添加触发组</el-button>
				</div>
				<div class="group-filter-item" v-else-if="isOnlyConditionGroup(group) || depth == 0">
					<el-button type="primary" @click="addRuleOrGroup('rule')" icon="el-icon-plus" text>添加条件</el-button>
					<el-button type="primary" @click="addRuleOrGroup('group')" icon="el-icon-plus"
						text>添加条件组</el-button>
					<el-button type="primary" @click="addRuleOrGroup('aggregate')" icon="el-icon-plus"
						text>添加聚合组</el-button>
				</div>
			</div>

		</transition>

		<div class="group-filter-logical drop-zone">
			<div @click="changeNot('not')" :class="{'isCollapsed':isCollapsed}" class="negation-badge"
				v-if="group?.condition?.startsWith('n')">
				非
			</div>
			<div :class="{'isCollapsed':isCollapsed}" class="aggregate-badge aggregate"
				v-if="group?.condition?.startsWith('aggregate')">
				聚合
			</div>
			<div :data-badge="group?.$badge" :class="{'isCollapsed':isCollapsed}" class="aggregate-badge badge"
				v-if="group?.$badge">
				{{group?.$badge}}
			</div>
			<span @click="changeNot('and')"
				:class="{ 'current-and': group.condition === 'and' || group.condition === 'nand' || group.condition === 'aggregate' }">且</span>
			<span @click="changeNot('or')"
				:class="{ 'current-or': group.condition === 'or' || group.condition === 'nor' }">或</span>
			<div class="group-filter-toggle">
				<el-button style="transform: scale(0.9)" type="success" size="small"
					:icon="isCollapsed ? 'el-icon-plus' : 'el-icon-minus'" circle
					@click="this.isCollapsed = !this.isCollapsed"></el-button>
			</div>
		</div>
	</div>
</template>

<script>
	import itemRule from './itemRule.vue'
	import MD5 from 'crypto-js/md5'
	export default {
		name: 'Group',
		inject: ['deleteRuleBy'],
		components: {
			itemRule
		},
		props: {
			group: {
				type: Object,
				required: true
			},
			depth: {
				type: Number,
				default: 0
			},
			options: Object,
		},
		data() {
			return {
				isCollapsed: false,
			}
		},
		computed: {
			model: {
				get() {
					return this.group
				},
				set(value) {
					this.$emit('update:group', value)
				}
			}
		},
		directives: {

		},
		methods: {
			addTrigger() {
				this.$message.error("触发订阅功能开发中...");
			},
			addFunction() {
				this.$message.error("执行函数功能开发中...");
			},
			uniqueId() {
				//return Math.floor(1e5 * Math.random());
				return Math.random().toString().slice(2, 10).padEnd(8, '0').substring(0, 8);
			},
			isConditionGroup(rule) {
				return 'condition' in rule && 'rules' in rule
			},
			isOnlyConditionGroup(group) {
				return !group.rules.some(t => "field" in t);
			},
			updateChildGroup(index, newGroup) {
				const newRules = [...this.group.rules]
				newRules.splice(index, 1, newGroup)
				this.$emit('update-group', {
					...this.group,
					rules: newRules
				})
			},
			// 获取 rule 和 group 的data
			getRuleOrGroupData(type) {
				const createRule = (badge) => ({
					$id: this.uniqueId(),
					$badge: badge,
					field: "",
					operator: "",
					value: "",
					type: "string"
				});

				const createGroup = (badge) => ({
					condition: "and",
					$badge: badge,
					$id: this.uniqueId(),
					rules: [createRule(badge), createRule(badge)]
				});

				let data = null;

				switch (type) {
					case 'aggregate':
						data = {
							condition: "aggregate",
							$id: this.uniqueId(),
							rules: [createRule(), createGroup('维度'), createGroup('指标')]
						};
						break;
					case 'group':
						data = createGroup();
						break;
					case 'rule':
						data = createRule();
						break;
					default:

				}

				return data;
			},
			// 复制规则
			copyRule(index) {
				let rule = JSON.parse(JSON.stringify(this.model.rules[index]))
				rule.$id = this.uniqueId();
				this.model.rules.splice(index + 1, 0, rule)
			},
			// 添加条件或者组
			addRuleOrGroup(type, index) {
				if (typeof index !== 'undefined') {
					this.model.rules.splice(index + 1, 0, this.getRuleOrGroupData(type))
					return;
				}
				this.model.rules.push(this.getRuleOrGroupData(type));
			},
			// 删除条件
			deleteChildRule(index) {
				this.model.rules.splice(index, 1)
				this.handleDelete(this.model.rules)
			},
			// 删除组
			deleteChildGroup(index) {
				let newRules
				const foolRulesNum = this.model.rules.filter((t) => {
					return "condition" in t
				}).length
				if (foolRulesNum === 1) {
					newRules = this.model.rules.filter((t) => {
						return !("condition" in t)
					})
					this.$emit('update-group', {
						...this.group,
						rules: newRules
					})
				} else {
					newRules = this.group.rules.filter((_, i) => i !== index)
				}
				this.handleDelete(newRules)
			},
			handleDelete(newRules) {
				if (newRules.length === 0) {
					this.$emit('delete-group')
				} else {
					this.$emit('update-group', {
						...this.group,
						rules: newRules
					})
				}
			},
			// 且和或
			changeCondition(condition) {
				this.$emit('update-group', {
					...this.group,
					condition
				})
			},
			// 与非 和 或非
			changeNot(condition) {

				const conditionMap = {
					not: {
						nand: 'and',
						nor: 'or',
					},
					and: {
						nor: 'nand',
						and: 'nand',
						or: 'and',
						nand: 'and'
					},
					or: {
						nor: 'or',
						or: 'nor',
						and: 'or',
						nand: 'nor'
					}
				};

				const current = this.group.condition;
				let newCondition = conditionMap[condition]?.[current];

				if (newCondition) {
					if (this.group?.$badge) {
						newCondition = newCondition.replace(/^n/, '');
					}
					this.changeCondition(newCondition);
				}
			},
			simpleHash(str) {
				str = JSON.stringify(str)
				return MD5(str).toString()
			},
			handleDragOver(e) {
				// 始终作用于父元素
				this.$refs.dropZone.classList.add('dragover');
			},
			handleDragLeave(e) {
				return this.$refs.dropZone.classList.remove('dragover');

				// 通过坐标检测是否仍在父元素区域
				/*
				const rect = this.$refs.dropZone.getBoundingClientRect();
				const isInside = e.clientX >= rect.left &&
					e.clientX <= rect.right &&
					e.clientY >= rect.top &&
					e.clientY <= rect.bottom;

				if (!isInside) {
					this.$refs.dropZone.classList.remove('dragover');
				}
				*/
			},
			handleDrop(e) {
				this.$refs.dropZone.classList.remove('dragover');
				const data = JSON.parse(e.dataTransfer.getData('text/plain'));
				if (data.$id) {
					this.deleteRuleBy(data.$id);
					data.$id = this.uniqueId();
					this.model.rules.push(data);
					this.deleteRuleBy([]);
				}
			}
		}
	}
</script>


<style scoped lang="scss">
	.group-filter-wrapper {
		border: 2px dashed #fff;
		border-radius: 5px;
		min-height: 70px;
		margin-top: 1px !important;
		margin-right: 1px !important;
	}

	.group-filter-wrapper.dragover {
		border: 2px dashed #42b883;
		background: rgba(0, 255, 0, 0.1) !important;
	}

	.group-filter-wrapper:has(> div.group-filter-logical > div.negation-badge:not(.isCollapsed)) {
		border: 2px dashed #ff4d4f;
		background: rgba(255, 77, 79, 0.05);
	}

	.group-filter-wrapper:has(> div.group-filter-logical > div.aggregate:not(.isCollapsed)) {
		border: 2px dashed #ff4d4f;
		background: rgba(255, 77, 79, 0.05);
	}

	.group-filter-logical {
		user-select: none;
		margin-left: 1px;
	}


	.negation-badge,
	.aggregate-badge {
		position: absolute;
		top: -8px;
		right: -8px;
		width: 20px;
		height: 20px;
		line-height: 20px;
		text-align: center;
		border-radius: 50%;
		background: #ff4d4f;
		color: white;
		font-size: 12px;
		cursor: pointer;
		box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
		transition: all 0.2s;
		z-index: 2;
	}

	.aggregate-badge {
		height: 30px;
		line-height: 12px;
		border-radius: 5px;
		padding-top: 4px;
		font-size: 11px;
		top: -4px;
	}

	.aggregate-badge.badge {
		//background-color: #4889a7;
		//background-color: #F59E0B;
		//background-color: #10B981;

		background-color: #2fa477;
	}

	.aggregate-badge.badge[data-badge='指标'] {
		//background-color: #F59E0B;
		background-color: #2fa477;
	}

	/* 定义垂直缩放动画 */
	.el-zoom-in-center-y-enter-active,
	.el-zoom-in-center-y-leave-active {
		transition: transform 0.3s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.3s cubic-bezier(0.23, 1, 0.32, 1);
		transform-origin: center;
		/* 变换原点在元素中心 */
	}

	.el-zoom-in-center-y-enter-from,
	.el-zoom-in-center-y-leave-to {
		opacity: 0;
		transform: scaleY(0);
		/* 垂直方向缩放为0 */
	}
</style>
